/////////////////////////////////////////////////////////////////////////////
// This file is part of the "Java-DAP" project, a Java implementation
// of the OPeNDAP Data Access Protocol.
//
// Copyright (c) 2007 OPeNDAP, Inc.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
/////////////////////////////////////////////////////////////////////////////
using System;
using System.Collections;
using System.IO;
using System.Text;
using NDODS.DAP;
using NDODS.DAP.Exceptions;
using NDODS.DAP.Primitives;
using NDODS.DAP.Utils;
using NDODS.DAP.XMLParser;

namespace NDODS.DAP.BaseTypes
{
    /// <summary> This abstract class defines the basic data type features for the OPeNDAP data
    /// access protocol (DAP) data types. All of the DAP type classes
    /// (<code>DFloat64</code>, <code>DArray</code>, etc.) subclass it or one of
    /// its two abstract descendents, <code>DVector</code> or
    /// <code>DConstructor</code>.
    /// <p/>
    /// These classes and their methods give a user the capacity to set up
    /// sophisticated data types. They do <em>not</em> provide sophisticated ways to
    /// access and use this data. On the server side, in many cases, the class
    /// instances will have no data in them at all until the <code>serialize</code>
    /// method is called to send data to the client. On the client side, most OPeNDAP
    /// application programs will unpack the data promptly into whatever local
    /// data structure the programmer deems the most useful.
    /// <p/>
    /// Descendents of this class should implement the <code>ClientIO</code>
    /// interface.  That interface defines a <code>Deserialize</code> method used
    /// by a OPeNDAP client to retrieve the variable's declaration and value(s) from
    /// a OPeNDAP server.
    /// 
    /// </summary>
    /// <author>  jehamby
    /// </author>
    /// <version>  $Revision: 15901 $
    /// </version>
    /// <seealso cref="DDS">
    /// </seealso>
    /// <seealso cref="IClientIO">
    /// </seealso>
    [Serializable]
    public abstract class BaseType : ICloneable
    {
        //UPGRADE_NOTE: Respective javadoc comments were merged.  It should be changed in order to comply with .NET documentation conventions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1199'"
        /// <summary> Returns the unencoded name of the class instance.
        /// 
        /// </summary>
        /// <returns> the name of the class instance.
        /// </returns>
        /// <summary> Sets the unencoded name of the class instance.
        /// 
        /// </summary>
        public virtual String ClearName
        {
            get { return _name; }

            set
            {
                _name = value;
                _attr.ClearName = value;
                _attrTbl.ClearName = value;
            }
        }

        //UPGRADE_NOTE: Respective javadoc comments were merged.  It should be changed in order to comply with .NET documentation conventions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1199'"
        /// <summary> Returns the WWW encoded name of the class instance.
        /// 
        /// </summary>
        /// <returns> the name of the class instance.
        /// </returns>
        /// <summary> Sets the name of the class instance.
        /// 
        /// </summary>
        public virtual String Name
        {
            get { return EscapeStrings.id2www(_name); }

            set { ClearName = EscapeStrings.www2id(value); }
        }

        /// <summary> Returns the OPeNDAP type name of the class instance as a <code>String</code>.
        /// 
        /// </summary>
        /// <returns> the OPeNDAP type name of the class instance as a <code>String</code>.
        /// </returns>
        public abstract String TypeName { get; }

        public virtual BaseType Parent
        {
            get { return (_myParent); }

            set { _myParent = value; }
        }

        public virtual String LongName
        {
            get
            {
   

                BaseType parent = _myParent;

                String longName = _name;


                while (parent != null)
                {
                    longName = parent.Name + "." + longName;
                    parent = parent.Parent;
                }
                return (longName);
            }
            // **************************************************************
            //
            // Attribute Table Methods
            //
            // ..............................................................
        }

        public virtual AttributeTable AttributeTable
        {
            get { return _attrTbl; }
        }

        public virtual ArrayList AttributeNames
        {
            get { return (_attrTbl.Names); }
        }

        internal const long serialVersionUID = 1;

        /// <summary> The name of this variable.</summary>
        private String _name;

        /// <summary> The parent (container class) of this object, if one exists</summary>
        private BaseType _myParent;

        /// <summary> The Attribute Table used to contain attributes specific to this
        /// instance of a BaseType variable. This is the repository for
        /// "Semantic Metadata"
        /// </summary>
        private Attribute _attr;

        private AttributeTable _attrTbl;

        /// <summary> Constructs a new <code>BaseType</code> with no name.</summary>
        public BaseType() : this(null)
        {
        }

        /// <summary> Constructs a new <code>BaseType</code> with name <code>n</code>.
        /// 
        /// </summary>
        /// <param name="n">the name of the variable.
        /// </param>
        public BaseType(String n) : this(n, true)
        {
        }

        /// <summary> Constructs a new <code>BaseType</code> with name <code>n</code>.
        /// 
        /// </summary>
        /// <param name="n">the name of the variable.
        /// </param>
        /// <param name="decodeName"></param>
        public BaseType(String n, bool decodeName)
        {
            if (decodeName)
                _name = EscapeStrings.www2id(n);
            else
                _name = n;


            _myParent = null;
            _attrTbl = new AttributeTable(_name);
            _attr = new Attribute(_name, _attrTbl);
        }

        /// <summary> Returns a clone of this <code>BaseType</code>.  A deep copy is performed
        /// on all data inside the variable.
        /// 
        /// </summary>
        /// <returns> a clone of this <code>BaseType</code>.
        /// </returns>
        public virtual Object Clone()
        {
            try
            {
                BaseType bt = (BaseType) MemberwiseClone();
                bt._name = _name;
                bt._attrTbl = (AttributeTable) this._attrTbl.Clone();
                bt._attr = new Attribute(Name, bt._attrTbl);
                return bt;
            }
                //UPGRADE_NOTE: Exception 'java.lang.CloneNotSupportedException' was converted to 'System.Exception' which has different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1100'"
            catch (Exception)
            {
                // this shouldn't happen, since we are Cloneable
                throw new ApplicationException();
            }
        }

        /// <summary> Returns the number of variables contained in this object. For simple and
        /// vector type variables, it always returns 1. To count the number
        /// of simple-type variable in the variable tree rooted at this variable, set
        /// <code>leaves</code> to <code>true</code>.
        /// 
        /// </summary>
        /// <param name="leaves">If true, count all the simple types in the `tree' of
        /// variables rooted at this variable.
        /// </param>
        /// <returns> the number of contained variables.
        /// </returns>
        public virtual int ElementCount(bool leaves)
        {
            return 1;
        }

        /// <summary> Returns the number of variables contained in this object. For simple and
        /// vector type variables, it always returns 1.
        /// 
        /// </summary>
        /// <returns> the number of contained variables.
        /// </returns>
        public int ElementCount()
        {
            return ElementCount(false);
        }


        /// <summary> Write the variable's declaration in a C-style syntax. This
        /// function is used to create textual representation of the Data
        /// Descriptor Structure (DDS).  See <em>The OPeNDAP User Manual</em> for
        /// information about this structure.
        /// 
        /// </summary>
        /// <param name="os">         The <code>StreamWriter</code> on which to Print the
        /// declaration.
        /// </param>
        /// <param name="space">      Each line of the declaration will begin with the
        /// characters in this string.  Usually used for leading spaces.
        /// </param>
        /// <param name="print_semi"> a bool value indicating whether to Print a
        /// semicolon at the end of the declaration.
        /// </param>
        /// <param name="constrained">a bool value indicating whether to Print
        /// the declartion dependent on the projection information. <b>This
        /// is only used by Server side code.</b>
        /// </param>
        /// <seealso cref="DDS">
        /// </seealso>
        public virtual void PrintDeclaration(StreamWriter os, String space, bool print_semi, bool constrained)
        {
            //System.out.println("BaseType.PrintDeclaration()...");
            os.Write(space + TypeName + " " + Name);
            if (print_semi)
            {
                //UPGRADE_TODO: Method 'java.io.StreamWriter.println' was converted to 'System.IO.TextWriter.WriteLine' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioStreamWriterprintln_javalangString'"
                os.WriteLine(";");
            }
        }

        /// <summary> Write the variable's declaration in a C-style syntax. This
        /// function is used to create textual representation of the Data
        /// Descriptor Structure (DDS).  See <em>The OPeNDAP User Manual</em> for
        /// information about this structure.
        /// 
        /// </summary>
        /// <param name="os">        The <code>StreamWriter</code> on which to Print the
        /// declaration.
        /// </param>
        /// <param name="space">     Each line of the declaration will begin with the
        /// characters in this string.  Usually used for leading spaces.
        /// </param>
        /// <param name="print_semi">a bool value indicating whether to Print a
        /// semicolon at the end of the declaration.
        /// </param>
        /// <seealso cref="DDS">
        /// </seealso>
        public virtual void PrintDeclaration(StreamWriter os, String space, bool print_semi)
        {
            PrintDeclaration(os, space, print_semi, false);
        }

        /// <summary> Print the variable's declaration.  Same as
        /// <code>PrintDeclaration(os, space, true)</code>.
        /// 
        /// </summary>
        /// <param name="os">   The <code>StreamWriter</code> on which to Print the
        /// declaration.
        /// </param>
        /// <param name="space">Each line of the declaration will begin with the
        /// characters in this string.  Usually used for leading spaces.
        /// </param>
        /// <seealso cref="DDS.Print(StreamWriter)">
        /// </seealso>
        public void PrintDeclaration(StreamWriter os, String space)
        {
            PrintDeclaration(os, space, true, false);
        }

        /// <summary> Print the variable's declaration.  Same as
        /// <code>PrintDeclaration(os, "    ", true)</code>.
        /// 
        /// </summary>
        /// <param name="os">The <code>StreamWriter</code> on which to Print the
        /// declaration.
        /// </param>
        /// <seealso cref="DDS.Print(StreamWriter)">
        /// </seealso>
        public void PrintDeclaration(StreamWriter os)
        {
            PrintDeclaration(os, "    ", true, false);
        }

        /// <summary> Print the variable's declaration using <code>OutputStream</code>.
        /// 
        /// </summary>
        /// <param name="os">        The <code>OutputStream</code> on which to Print the
        /// declaration.
        /// </param>
        /// <param name="space">     Each line of the declaration will begin with the
        /// characters in this string.  Usually used for leading spaces.
        /// </param>
        /// <param name="print_semi">a bool value indicating whether to Print a
        /// semicolon at the end of the declaration.
        /// </param>
        /// <param name="constrained"></param>
        /// <seealso cref="DDS.Print(StreamWriter)">
        /// </seealso>
        public void PrintDeclaration(Stream os, String space, bool print_semi, bool constrained)
        {
            //UPGRADE_WARNING: At least one expression was used more than once in the target code. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1181'"
            StreamWriter pw =
                new StreamWriter(
                    new StreamWriter(new StreamWriter(os, Encoding.Default).BaseStream,
                                     new StreamWriter(os, Encoding.Default).Encoding).BaseStream,
                    new StreamWriter(new StreamWriter(os, Encoding.Default).BaseStream,
                                     new StreamWriter(os, Encoding.Default).Encoding).Encoding);
            PrintDeclaration(pw, space, print_semi, constrained);
            pw.Flush();
        }

        /// <summary> Print the variable's declaration using <code>OutputStream</code>.
        /// 
        /// </summary>
        /// <param name="os">        The <code>OutputStream</code> on which to Print the
        /// declaration.
        /// </param>
        /// <param name="space">     Each line of the declaration will begin with the
        /// characters in this string.  Usually used for leading spaces.
        /// </param>
        /// <param name="print_semi">a bool value indicating whether to Print a
        /// semicolon at the end of the declaration.
        /// </param>
        /// <seealso cref="DDS.Print(StreamWriter)">
        /// </seealso>
        public void PrintDeclaration(Stream os, String space, bool print_semi)
        {
            PrintDeclaration(os, space, print_semi, false);
        }

        /// <summary> Print the variable's declaration.  Same as
        /// <code>PrintDeclaration(os, space, true)</code>.
        /// 
        /// </summary>
        /// <param name="os">   The <code>OutputStream</code> on which to Print the
        /// declaration.
        /// </param>
        /// <param name="space">Each line of the declaration will begin with the
        /// characters in this string.  Usually used for leading spaces.
        /// </param>
        /// <seealso cref="DDS.Print(StreamWriter)">
        /// </seealso>
        public void PrintDeclaration(Stream os, String space)
        {
            //UPGRADE_WARNING: At least one expression was used more than once in the target code. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1181'"
            StreamWriter pw =
                new StreamWriter(
                    new StreamWriter(new StreamWriter(os, Encoding.Default).BaseStream,
                                     new StreamWriter(os, Encoding.Default).Encoding).BaseStream,
                    new StreamWriter(new StreamWriter(os, Encoding.Default).BaseStream,
                                     new StreamWriter(os, Encoding.Default).Encoding).Encoding);
            PrintDeclaration(pw, space);
            pw.Flush();
        }

        /// <summary> Print the variable's declaration.  Same as
        /// <code>PrintDeclaration(os, "    ", true)</code>.
        /// 
        /// </summary>
        /// <param name="os">The <code>OutputStream</code> on which to Print the
        /// declaration.
        /// </param>
        /// <seealso cref="DDS.Print(StreamWriter)">
        /// </seealso>
        public void PrintDeclaration(Stream os)
        {
            //UPGRADE_WARNING: At least one expression was used more than once in the target code. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1181'"
            StreamWriter pw =
                new StreamWriter(
                    new StreamWriter(new StreamWriter(os, Encoding.Default).BaseStream,
                                     new StreamWriter(os, Encoding.Default).Encoding).BaseStream,
                    new StreamWriter(new StreamWriter(os, Encoding.Default).BaseStream,
                                     new StreamWriter(os, Encoding.Default).Encoding).Encoding);
            PrintDeclaration(pw);
            pw.Flush();
        }


        /// <summary> Prints the value of the variable, with its declaration.  This
        /// function is primarily intended for debugging OPeNDAP applications and
        /// text-based clients such as geturl.
        /// 
        /// </summary>
        /// <param name="os">          the <code>StreamWriter</code> on which to Print the value.
        /// </param>
        /// <param name="space">       this value is passed to the <code>PrintDeclaration</code> method,
        /// and controls the leading spaces of the output.
        /// </param>
        /// <param name="print_decl_p">a bool value controlling whether the
        /// variable declaration is printed as well as the value.
        /// </param>
        public abstract void PrintValue(StreamWriter os, String space, bool print_decl_p);

        /// <summary> Print the variable's value.  Same as
        /// <code>PrintValue(os, space, true)</code>.
        /// 
        /// </summary>
        /// <param name="os">   the <code>StreamWriter</code> on which to Print the value.
        /// </param>
        /// <param name="space">this value is passed to the <code>PrintDeclaration</code> method,
        /// and controls the leading spaces of the output.
        /// </param>
        /// <seealso cref="DataDDS.PrintValue(StreamWriter, String)">
        /// </seealso>
        public void PrintValue(StreamWriter os, String space)
        {
            PrintValue(os, space, true);
        }

        /// <summary> Print the variable's value using <code>OutputStream</code>.
        /// 
        /// </summary>
        /// <param name="os">          the <code>OutputStream</code> on which to Print the value.
        /// </param>
        /// <param name="space">       this value is passed to the <code>PrintDeclaration</code> method,
        /// and controls the leading spaces of the output.
        /// </param>
        /// <param name="print_decl_p">a bool value controlling whether the
        /// variable declaration is printed as well as the value.
        /// </param>
        /// <seealso cref="DataDDS.PrintValue(StreamWriter, String, bool)">
        /// </seealso>
        public void PrintValue(Stream os, String space, bool print_decl_p)
        {
            //UPGRADE_WARNING: At least one expression was used more than once in the target code. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1181'"
            StreamWriter pw = new StreamWriter(os, Encoding.Default);
            PrintValue(pw, space, print_decl_p);
            pw.Flush();
        }

        /// <summary> Print the variable's value using <code>OutputStream</code>.
        /// 
        /// </summary>
        /// <param name="os">   the <code>OutputStream</code> on which to Print the value.
        /// </param>
        /// <param name="space">this value is passed to the <code>PrintDeclaration</code> method,
        /// and controls the leading spaces of the output.
        /// </param>
        /// <seealso cref="DataDDS.PrintValue(StreamWriter, String)">
        /// </seealso>
        public void PrintValue(Stream os, String space)
        {
            //UPGRADE_WARNING: At least one expression was used more than once in the target code. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1181'"
            StreamWriter pw = new StreamWriter(os, Encoding.Default);
            PrintValue(pw, space);
            pw.Flush();
        }

        /// <summary> Checks for internal consistency.  This is important to check for complex
        /// constructor classes.
        /// For example, an <code>DInt32</code> instance would return false if it had
        /// no name defined.  A <code>DGrid</code> instance might return false for
        /// more complex reasons, such as having Map arrays of the wrong
        /// size or shape.
        /// <p/>
        /// This method is used by the <code>DDS</code> class, and will rarely, if
        /// ever, be explicitly called by a OPeNDAP application program.  A
        /// variable must pass this test before it is sent, but there may be
        /// many other stages in a retrieve operation where it would fail.
        /// 
        /// </summary>
        /// <param name="all">For complex constructor types (
        /// <code>DGrid</code>, <code>DSequence</code>, <code>DStructure</code>),
        /// this flag indicates whether to check the
        /// semantics of the member variables, too.
        /// </param>
        /// <throws>  BadSemanticsException if semantics are bad, explains why. </throws>
        /// <seealso cref="CheckSemantics(bool)">
        /// </seealso>
        public virtual void CheckSemantics(bool all)
        {
            if (_name == null)
                throw new BadSemanticsException("BaseType.CheckSemantics(): Every variable must have a name");
        }

        /// <summary> Check semantics.  Same as <code>CheckSemantics(false)</code>.
        /// 
        /// </summary>
        /// <throws>  BadSemanticsException if semantics are bad, explains why. </throws>
        /// <seealso cref="CheckSemantics(bool)">
        /// </seealso>
        public void CheckSemantics()
        {
            CheckSemantics(false);
        }

        /// <summary> Constructs a new <code>PrimitiveVector</code> object optimized for the
        /// particular data type of this <code>BaseType</code>.  For example, a
        /// <code>DByte</code> class would create a new
        /// <code>BytePrimitiveVector</code> in this call.  This allows for a very
        /// optimized, yet type-safe, implementation of <code>DVector</code>
        /// functionality.  For non-primitive types, such as
        /// <code>DArray</code>, <code>DGrid</code>, <code>DSequence</code>, and
        /// <code>DStructure</code>, the default implementation returns a
        /// <code>BaseTypePrimitiveVector</code> object which can
        /// Deserialize an array of complex types.
        /// 
        /// </summary>
        /// <returns> a new <code>PrimitiveVector</code> object for the variable type.
        /// </returns>
        public virtual PrimitiveVector NewPrimitiveVector()
        {
            return new BaseTypePrimitiveVector(this);
        }


        public virtual bool HasAttributes()
        {
            IEnumerator e = _attrTbl.Names.GetEnumerator();

            //UPGRADE_TODO: Method 'java.util.Enumeration.hasMoreElements' was converted to 'System.Collections.IEnumerator.MoveNext' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationhasMoreElements'"
            if (e.MoveNext())
                return (true);

            return (false);
        }


        public virtual Attribute GetAttribute()
        {
            return _attr;
        }

        public virtual void addAttributeAlias(String alias, String attributeName)
        {
            _attrTbl.addAlias(alias, attributeName);
        }

        public virtual void AppendAttribute(String name, int type, String value_Renamed, bool check)
        {
            _attrTbl.appendAttribute(name, type, value_Renamed, check);
        }

        public virtual void AppendAttribute(String name, int type, String value_Renamed)
        {
            _attrTbl.appendAttribute(name, type, value_Renamed);
        }

        public virtual void addAttributeContainer(AttributeTable at)
        {
            _attrTbl.addContainer(at.Name, at);
        }

        public virtual AttributeTable appendAttributeContainer(String name)
        {
            return (_attrTbl.appendContainer(name));
        }

        public virtual void delAttribute(String name)
        {
            _attrTbl.delAttribute(name);
        }

        public virtual void delAttribute(String name, int i)
        {
            _attrTbl.delAttribute(name, i);
        }

        public virtual Attribute GetAttribute(String name)
        {
            return (_attrTbl.getAttribute(name));
        }

        public virtual void PrintAttributes(Stream os)
        {
            _attrTbl.print(os);
        }

        public virtual void PrintAttributes(Stream os, String pad)
        {
            _attrTbl.print(os, pad);
        }

        public virtual void PrintAttributes(StreamWriter pw)
        {
            _attrTbl.print(pw);
        }

        public virtual void PrintAttributes(StreamWriter pw, String pad)
        {
            _attrTbl.print(pw, pad);
        }


        /// <summary> </summary>
        /// <param name="os">
        /// </param>
        /// <opendap.ddx.experimental>  </opendap.ddx.experimental>
        public virtual void PrintXML(Stream os)
        {
            PrintXML(os, "");
        }


        /// <summary> </summary>
        /// <param name="os">
        /// </param>
        /// <param name="pad">
        /// </param>
        /// <opendap.ddx.experimental>  </opendap.ddx.experimental>
        public virtual void PrintXML(Stream os, String pad)
        {
            //UPGRADE_WARNING: At least one expression was used more than once in the target code. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1181'"
            StreamWriter pw =
                new StreamWriter(
                    new StreamWriter(new StreamWriter(os, Encoding.Default).BaseStream,
                                     new StreamWriter(os, Encoding.Default).Encoding).BaseStream,
                    new StreamWriter(new StreamWriter(os, Encoding.Default).BaseStream,
                                     new StreamWriter(os, Encoding.Default).Encoding).Encoding);
            PrintXML(pw, pad, false);
            pw.Flush();
        }


        /// <summary> </summary>
        /// <param name="pw">
        /// </param>
        /// <opendap.ddx.experimental>  </opendap.ddx.experimental>
        public virtual void PrintXML(StreamWriter pw)
        {
            PrintXML(pw, "");
        }


        /// <summary> </summary>
        /// <param name="pw">
        /// </param>
        /// <param name="pad">
        /// </param>
        /// <opendap.ddx.experimental>  </opendap.ddx.experimental>
        public virtual void PrintXML(StreamWriter pw, String pad)
        {
            PrintXML(pw, pad, false);
        }

        /// <summary> </summary>
        /// <param name="pw">
        /// </param>
        /// <param name="pad">
        /// </param>
        /// <param name="constrained">
        /// </param>
        /// <opendap.ddx.experimental>  </opendap.ddx.experimental>
        public virtual void PrintXML(StreamWriter pw, String pad, bool constrained)
        {
            pw.Write(pad + "<" + TypeName);
            if (_name != null)
            {
                pw.Write(" name=\"" + DDSXMLParser.normalizeToXML(_name) + "\"");
            }

            IEnumerator e = AttributeNames.GetEnumerator();
            //UPGRADE_TODO: Method 'java.util.Enumeration.hasMoreElements' was converted to 'System.Collections.IEnumerator.MoveNext' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationhasMoreElements'"
            if (e.MoveNext())
            {
                //UPGRADE_TODO: Method 'java.io.StreamWriter.println' was converted to 'System.IO.TextWriter.WriteLine' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioStreamWriterprintln_javalangString'"
                pw.WriteLine(">");
                //UPGRADE_TODO: Method 'java.util.Enumeration.hasMoreElements' was converted to 'System.Collections.IEnumerator.MoveNext' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationhasMoreElements'"
                while (e.MoveNext())
                {
                    //UPGRADE_TODO: Method 'java.util.Enumeration.nextElement' was converted to 'System.Collections.IEnumerator.Current' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationnextElement'"
                    String aName = (String) e.Current;

                    try
                    {
                        Attribute a = GetAttribute(aName);
                        a.printXML(pw, pad + "\t", constrained);
                    }
                    catch (NoSuchAttributeException)
                    {
                    }
                }
                //UPGRADE_TODO: Method 'java.io.StreamWriter.println' was converted to 'System.IO.TextWriter.WriteLine' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioStreamWriterprintln_javalangString'"
                pw.WriteLine(pad + "</" + TypeName + ">");
            }
            else
            {
                //UPGRADE_TODO: Method 'java.io.StreamWriter.println' was converted to 'System.IO.TextWriter.WriteLine' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioStreamWriterprintln_javalangString'"
                pw.WriteLine("/>");
            }
        }
    }
}